#include <iostream>

#include "Databank.hpp"
#include "ItemManager.hpp"
#include "Log.hpp"

#include "Town.hpp"

Building::Building(Zone* zone) : Area(zone)
{
}

Building::~Building()
{
}

EBuildingType Building::getBuildingType()
{
	return BuildingType;
}

void Building::generate(int x, int y, int w, int h, int subdivs)
{
	TCODBsp* bsp = new TCODBsp(x, y, w+2, h+2);
	bsp->splitRecursive(NULL, subdivs, 4, 4, 1.0f, 1.0f);
	bsp->traverseLevelOrder(this, NULL);
	delete bsp;
}

void Building::setBuildingType(EBuildingType type)
{
	BuildingType = type;
}

bool Building::visitNode(TCODBsp* node, void* userData)
{
	int xmin = node->x;
	int xmax = node->x+node->w-3;
	int ymin = node->y;
	int ymax = node->y+node->h-3;

	node->x = xmin;
	node->y = ymin;
	node->w = xmax-xmin;
	node->h = ymax-ymin;

	if ((unsigned)xmax+1 >= Area->TileData.size()-1 || (unsigned)ymax+1 >= Area->TileData.size()-1)
		return true;

	for (int x = xmin; x <= xmax; ++x)
		for (int y = ymin; y <= ymax; ++y)
		{
			if (x == xmin || x == xmax || y == ymin || y == ymax)
			{
				//delete Area->TileData[x][y];
				Area->TileData[x][y]->addItem(Item::addItem("wall", Vector2d(x, y), Area)); //= new Tile(ETT_NONE, "wall", '#', Vector2d(x, y), Area, false, false);
			}
			else
			{	
				//delete Area->TileData[x][y];
				Area->TileData[x][y]->addItem(Item::addItem("floor", Vector2d(x, y), Area)); //= new Tile(ETT_NONE, "floor", '.', Vector2d(x, y), Area, true, true);
			}
		}

	int doordir = TCODRandom::getInstance()->getInt(0, 3);
	switch (doordir)
	{
	case 0: // north
//		Area->TileData[node->x+(node->w/2)][node->y] = new Door(Vector2d(node->x+(node->w/2), node->y), Area);
		break;

	case 1: // south
//		Area->TileData[node->x+(node->w/2)][node->y+node->h] = new Door(Vector2d(node->x+(node->w/2), node->y+node->h), Area);
		break;

	case 2: // east
//		Area->TileData[node->x+node->w][node->y+(node->h/2)] = new Door(Vector2d(node->x+node->w, node->y+(node->h/2)), Area);
		break;
		
	case 3: // west
//		Area->TileData[node->x][node->y+(node->h/2)] = new Door(Vector2d(node->x, node->y+(node->h/2)), Area);
		break;

	default:
		Log::write("CRIT: Invalid door placement direction.");
		exit(1);
	}

	return true;
}

Town::~Town()
{
	TileData.clear();
	delete ViewMap;
}

void Town::generate(std::string name)
{
	Name = name;

	TileData.resize(100, std::vector<Tile*>(100, NULL));
	ViewMap = new TCODMap(100, 100);

	for (unsigned int x = 0; x < 100; ++x)
		for (unsigned int y = 0; y < 100; ++y)
		{
			TileData[x][y] = new Tile(Vector2d(x, y), this);
			/*delete TileData[x][y];
			TileData[x][y] = new BurnableTile(BURNABLE["grass"]->Name, 
				BURNABLE["grass"]->Shape, Vector2d(x, y), this, BURNABLE["grass"]->Passable, BURNABLE["grass"]->Transparent,
				BURNABLE["grass"]->BurnTimer, BURNABLE["grass"]->Flammability, BURNABLE["grass"]->Spreads, BURNABLE["grass"]->ForeCol, BURNABLE["grass"]->BackCol);*/
		}

	BSP = new TCODBsp(2, 2, TileData.size()-2, TileData[0].size()-2);
	BSP->splitRecursive(NULL, 6, 6, 6, 1.5f, 1.5f);
	BSP->traverseInvertedLevelOrder(this, NULL);
	delete BSP;

	for (unsigned int x = 0; x < 100; ++x)
		for (unsigned int y = 0; y < 100; ++y)
			if (TileData[x][y]->getItems().size() == 0)
				TileData[x][y]->addItem(Item::addItem("grass", Vector2d(x, y), this));

	/*for (unsigned int x = 0; x < 100; ++x)
		for (unsigned int y = 0; y < 100; ++y)
			if (TileData[x][y]->getName() == "grass")
			{
				int percent = TCODRandom::getInstance()->getInt(1, 100);
				if (percent > 99)
					TileData[x][y] = new BurnableTile(BURNABLE["tree"]->Name, 
				BURNABLE["tree"]->Shape, Vector2d(x, y), this, BURNABLE["tree"]->Passable, BURNABLE["tree"]->Transparent,
				BURNABLE["tree"]->BurnTimer, BURNABLE["tree"]->Flammability, BURNABLE["tree"]->Spreads, BURNABLE["tree"]->ForeCol, BURNABLE["tree"]->BackCol);
			}

	for (unsigned int x = 0; x < 100; ++x)
		for (unsigned int y = 0; y < 100; ++y)
			if (TileData[x][y]->getName() == "grass")
			{
				int percent = TCODRandom::getInstance()->getInt(1, 100);
				if (percent > 99)
					TileData[x][y] = new BurnableTile(BURNABLE["bush"]->Name, 
				BURNABLE["bush"]->Shape, Vector2d(x, y), this, BURNABLE["bush"]->Passable, BURNABLE["bush"]->Transparent,
				BURNABLE["bush"]->BurnTimer, BURNABLE["bush"]->Flammability, BURNABLE["bush"]->Spreads, BURNABLE["bush"]->ForeCol, BURNABLE["bush"]->BackCol);
			}*/
}

bool Town::visitNode(TCODBsp* node, void* userData)
{
	if (node->isLeaf())
	{
		int xmin = node->x;
		int xmax = node->x+node->w;
		int ymin = node->y;
		int ymax = node->y+node->h;

		if (xmin == 0) ++xmin;
		if (ymin == 0) ++ymin;

		if (xmax == TileData.size()) --xmax;
		if (ymax == TileData[0].size()) --ymax;
		
		node->x = xmin+2;
		node->y = ymin+2;
		node->w = xmax-xmin-2;
		node->h = ymax-ymin-2;

		/*for (int x = node->x; x < node->x+node->w; ++x)
			for (int y = node->y; y < node->y+node->h; ++y)
				TileData[x][y]->setColor(TCODColor::green, TCODColor::red);*/

		if (node->w < 4+2 || node->h < 4+2)
			return true;

		int buildx = TCODRandom::getInstance()->getInt(node->x, node->x+node->w-4-2);
		int buildy = TCODRandom::getInstance()->getInt(node->y, node->y+node->h-4-2);
		int buildw = TCODRandom::getInstance()->getInt(6, node->x+node->w-buildx);
		int buildh = TCODRandom::getInstance()->getInt(6, node->y+node->h-buildy);

		Building* building = new Building(this);
		building->generate(buildx, buildy, buildw, buildh, 0);
		delete building;
	}
	return true;
}
